package org.zw.store.common;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.util.StringUtils;
import org.zw.store.common.exception.NotAuthenticationException;

public class TokenUtils {

    public static String SECRET = "heisenberg";//密钥

    public static long expire_time = 100;//过期时间，单位，秒

    /**
     * 生成一个登录令牌
     * @param tokenUser
     * @return
     */
    public static String loginSign(TokenUser tokenUser){

        Algorithm algorithm = Algorithm.HMAC256(SECRET);

        JWTCreator.Builder builder = JWT.create()
                .withClaim(TokenUser.CLAIM_NAME_TYPE, tokenUser.getType())
                .withClaim(TokenUser.CLAIM_NAME_USERID, tokenUser.getUserId())
                .withClaim(TokenUser.CLAIM_NAME_USERNAME, tokenUser.getUserName());

        if(tokenUser.isAdmin()){
            if(tokenUser.getShopId() != null && StringUtils.hasText(tokenUser.getShopName())){
                builder.withClaim(TokenUser.CLAIM_NAME_USERID,tokenUser.getShopId())
                        .withClaim(TokenUser.CLAIM_NAME_SHOPNAME,tokenUser.getShopName());
            }
        }

        String token = builder.sign(algorithm);
        return token;
    }

    /**
     * 从客户端令牌中获取用户信息
     * @param clientToken
     * @return
     */
    public static TokenUser getTokenUser(String clientToken){

        if(!StringUtils.hasText(clientToken)){//令牌为空
            throw new NotAuthenticationException("令牌为空！请登录");
        }

        DecodedJWT decodedJWT = null;
        try {
            decodedJWT = JWT.decode(clientToken);
        } catch (JWTDecodeException e) {
            throw new NotAuthenticationException("令牌错误！请登录");
        }

        Integer type = decodedJWT.getClaim(TokenUser.CLAIM_NAME_TYPE).asInt();
        if(type == null){
            throw new NotAuthenticationException("令牌无用户类型！请登录");
        }

        String userId = decodedJWT.getClaim(TokenUser.CLAIM_NAME_USERID).asString();
        String userName = decodedJWT.getClaim(TokenUser.CLAIM_NAME_USERNAME).asString();
        if(!StringUtils.hasText(userId) || !StringUtils.hasText(userName)){
            throw new NotAuthenticationException("令牌无用户信息！请登录");
        }

        if(TokenUser.TYPE_ADMIN.equals(type)){
            Integer shopId = decodedJWT.getClaim(TokenUser.CLAIM_NAME_SHOPID).asInt();
            String shopName = decodedJWT.getClaim(TokenUser.CLAIM_NAME_SHOPNAME).asString();

            return TokenUser.createAdmin(userId,userName,shopId,shopName);
        }
        return TokenUser.createUser(userId,userName);
    }

    /**
     * 校验客户端令牌,如果验证不通过,抛出自定义异常 NotAuthenticationException(未认证)
     * @param clientToken
     * @return
     */
    public static TokenUser verify(String clientToken){

        TokenUser tokenUser = getTokenUser(clientToken);

        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();//得到一个验证器
        try {
            verifier.verify(clientToken);
            return tokenUser;
        } catch (TokenExpiredException e){
            throw new NotAuthenticationException("令牌超时失效");
        } catch (JWTVerificationException e) {
            throw new NotAuthenticationException("令牌非法！请登录");
        }

    }
}
